#!/usr/bin/env python3
# @Date    : 2022-03-12
# @Author  : Bright (brt2@qq.com)
# @Link    : https://gitee.com/brt2
# @Version : 0.1.0

import json

def dump_km_as_mkm(dict_km, path_save):
    dict_ = km_to_mkm(dict_km)
    save_as_json(dict_, path_save)

def load_mkm_as_km(path_mkm):
    with open(path_mkm, "r", encoding="utf8") as fp:
        dict_mkm = json.load(fp)
    return mkm_to_km(dict_mkm)

class MkmParseError(Exception):
    """ mkm文件解析失败 """

#####################################################################

def _rename(node, old, new):
    if old in node:
        assert new not in node
        node[new] = node[old]
        del node[old]

def _rm_null_data(node, keyword, condition=None):
    if keyword not in node["data"]:
        return
    state = condition == "always" or condition == node["data"][keyword] if condition else node["data"][keyword]
    if state:
        del node["data"][keyword]

def _rename_or_rm(node, old_kw, new_kw, condition=None):
    """ 结合_rm_null_data() & _rename()
        if new_kw is None, always rm the item
    """
    # _rm_null_data
    if old_kw in node:
        state = condition == node[old_kw] if condition else (new_kw is None) or (not node[old_kw])
        if state:
            del node[old_kw]
        else:
            # rename
            node[new_kw] = node[old_kw]
            del node[old_kw]

def _recover_name(node, origin_kw, mkm_kw, condition=None):
    """ condition 没有作用，只是为了方便 _rename_or_rm() 的迁移 """
    if mkm_kw in node:
        node[origin_kw] = node[mkm_kw]
        del node[mkm_kw]

def km_to_mkm(dict_km):
    def format_node(node):
        if "children" in node:  # 递归子节点
            for child in node["children"]:
                format_node(child)

        # 处理curr_node:
        _rename_or_rm(node["data"], "text", "t")
        _rename_or_rm(node["data"], 'color', "c", "black")
        _rename_or_rm(node["data"], 'background', "b", "transparent")
        _rename_or_rm(node["data"], 'hyperlink', "h")
        _rename_or_rm(node["data"], 'hyperlinkTitle', "H")
        _rename_or_rm(node["data"], 'image', "i")
        _rename_or_rm(node["data"], 'imageTitle', "I")
        _rename_or_rm(node["data"], 'imageSize', "S")
        _rename_or_rm(node["data"], 'expandState', "e", "expand")
        _rename_or_rm(node["data"], 'priority', "p")
        _rename_or_rm(node["data"], 'progress', "P")
        _rename_or_rm(node["data"], 'note', "n")

        _rename_or_rm(node["data"], 'font-family', "f")
        _rename_or_rm(node["data"], 'font-size', "F")
        _rename_or_rm(node["data"], 'font-weight', "w")  # bold
        _rename_or_rm(node["data"], 'font-style', "s")  # italic
        _rename_or_rm(node["data"], 'layout', "l")
        _rename_or_rm(node["data"], 'layout_mind_offset', "L")

        # 删除created & id
        _rename_or_rm(node["data"], "id", None)
        _rename_or_rm(node["data"], "created", None)

        # _rename_or_rm(node, "data", "D")  # 存在bug：即使data为空字符串，也不能删除该字段
        node["D"] = node["data"]
        del node["data"]

        _rename_or_rm(node, "children", "C")

    # 遍历dict节点
    format_node(dict_km["root"])
    return dict_km

def save_as_json(dict_data, path_save):
    with open(path_save, "w", encoding="utf8") as fp:
        json.dump(dict_data, fp, separators=(",\n", ":"), ensure_ascii=False)

def save_as_yaml(dict_data, path_save):
    raise NotImplementedError()

def mkm_to_km(dict_mkm):
    def format_node(node):
        if "C" in node:  # 递归子节点
            for child in node["C"]:
                format_node(child)
        try:
            # 处理curr_node:
            _recover_name(node["D"], "text", "t")
            _recover_name(node["D"], 'color', "c")
            _recover_name(node["D"], 'background', "b", "transparent")
            _recover_name(node["D"], 'hyperlink', "h")
            _recover_name(node["D"], 'hyperlinkTitle', "H")
            _recover_name(node["D"], 'image', "i")
            _recover_name(node["D"], 'imageTitle', "I")
            _recover_name(node["D"], 'imageSize', "S")
            _recover_name(node["D"], 'expandState', "e", "expand")
            _recover_name(node["D"], 'priority', "p")
            _recover_name(node["D"], 'progress', "P")
            _recover_name(node["D"], 'note', "n")

            _recover_name(node["D"], 'font-family', "f")
            _recover_name(node["D"], 'font-size', "F")
            _recover_name(node["D"], 'font-weight', "w")  # bold
            _recover_name(node["D"], 'font-style', "s")  # italic
            _recover_name(node["D"], 'layout', "l")
            _recover_name(node["D"], 'layout_mind_offset', "L")

            # 删除created & id
            _recover_name(node["D"], "id", None)
            _recover_name(node["D"], "created", None)

            _recover_name(node, "data", "D")
            _recover_name(node, "children", "C")
        except KeyError as e:
            from pprint import pformat
            raise MkmParseError(f"未检索到关键字【{e}】，引发KeyError\n产生异常的NodeData >>>\n{pformat(node)}")

    # 遍历dict节点
    if "root" in dict_mkm:
        format_node(dict_mkm["root"])
    # 存储为yaml
    return dict_mkm


if __name__ == "__main__":
    path_mkm = "./tmp.json"
    with open("../mindmap/tmp/test.km", "r", encoding="utf8") as fp:
        dict_km = json.load(fp)

    dict_mkm = km_to_mkm(dict_km)
    save_as_json(dict_mkm, path_mkm)

    dict_km = load_mkm_as_km(path_mkm)
    print(">>>", dict_km)
